package com.inwk.valoepi.pages;

import java.util.ArrayList;
import java.util.List;

import org.openqa.selenium.By;
import org.openqa.selenium.ElementNotVisibleException;
import org.openqa.selenium.InvalidElementStateException;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import com.inwk.valoepi.managers.PageManager;
import com.inwk.valoepi.model.Product;

import static com.inwk.valoepi.util.MiscUtils.isOnlyDigits;

public class ShopPage extends AuthorizedPage {

	private String shopPageURLPart = "Product-list/";
	
	public ShopPage(PageManager pm) {
		super(pm);
		// TODO Auto-generated constructor stub
	}
	
	private boolean isAvailableForAdding(WebElement productDiv){
		try {
			wait.until(ExpectedConditions.visibilityOf(productDiv.findElement(By.cssSelector(".mini-qty-box"))));
			return true;
		} catch(TimeoutException e) {
			return false;
		}
	}
	
	public boolean addToCart(Product product) {
		
		WebElement productCard = findProduct(product);
		if(productCard != null) {
			if(isAvailableForAdding(productCard)) {
				WebElement cartCountDiv;
				try { 
					cartCountDiv = (new WebDriverWait(webDriver, 5)).until(ExpectedConditions.visibilityOfElementLocated(By.xpath(cartXPathLocator + "//*[@id='headerCartCount']")));
				} catch(TimeoutException e) {
					cartCountDiv = null;
				}
				String initialProductsQuantity = "1";
				if(cartCountDiv != null) {
					initialProductsQuantity = cartCountDiv.getText();
				}
				WebElement addDiv = productCard.findElement(By.className("product-add"));
				WebElement quantityInput = addDiv.findElement((By.tagName("input")));
				quantityInput.clear();
				quantityInput.sendKeys(product.getQuantity());
				WebElement cartSpan = addDiv.findElement(By.tagName("span"));
				//new Actions(webDriver).moveToElement(cartSpan).click().perform();
				cartSpan.click();
				
				if(cartCountDiv != null) {
					int number = Integer.parseInt(initialProductsQuantity) + 1;
					wait.until(ExpectedConditions.textToBePresentInElement(By.xpath(cartXPathLocator + "//*[@id='headerCartCount']"), String.valueOf(number)));
				} else {
					wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(cartXPathLocator + "//*[@id='headerCartCount']")));
				} 
			}
			return true;
		}
		return false;
	}
	
	private WebElement findProduct(Product product) {
		int numberOfPages = getShopPagesNumber();
		selectShopPageByNumber(1);
		for(int i = 1; i <= numberOfPages + 1; i++) {
			List<WebElement> lst = wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(By.xpath("//div[@class='product-listing grid-view']//div[contains(@class,'item-product')]")));
			for(WebElement we : lst) {				
				WebElement idDiv;
				try {
					idDiv = we.findElement(By.cssSelector(".product-id"));
				} catch (NoSuchElementException e) {
					idDiv = we.findElement(By.cssSelector("product-id.short"));
				}
				if(idDiv.getText().contains(product.getId())) {
					return we;
				}
			}
			if(i > 1) {
				WebElement staleElement = lst.get(0);
				selectShopPageByNumber(i);
				wait.until(ExpectedConditions.stalenessOf(staleElement));
			}
		}	
		return null;
	}
	
	private void selectShopPageByNumber(int pageNumber) {
		String targetURL;
		String currentURL = webDriver.getCurrentUrl();
		if(pageNumber >= 1 && pageNumber <= getShopPagesNumber()) {
			if(currentURL.endsWith(shopPageURLPart)) {
				targetURL = currentURL + "?p=" + pageNumber;
			} else {
				targetURL = currentURL.substring(0, currentURL.length() - 1) + pageNumber;
			}
			webDriver.get(targetURL);
		}
	}
	
	private int getShopPagesNumber() {
		List<WebElement> lst = wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(By.xpath("//span[contains(@id,'DataPagerFooter')]/a")));
		List<String> lstLinkText = new ArrayList<String>();
		for(WebElement we : lst) {
			String linkText = we.getText();
			if(isOnlyDigits(linkText)) {
				lstLinkText.add(we.getText());
			}
		}
		int number = 1;
		for(String str : lstLinkText) {
			if(Integer.parseInt(str) > number) {
				number = Integer.parseInt(str);
			}
		}
		return number;
	}

	@Override
	public boolean isCurrentPage() {
		if(webDriver.getCurrentUrl().contains(shopPageURLPart)) {
			return true;
		} else {
			return false;
		}
	}
}
